/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = cnaps2.c                                           */
/*  NOTE      =                                                    */
/*  DATE      = 2016/01/11 by songbb                               */
/*******************************************************************/


#include <sys/time.h>
#include <frreport_comm.h>
#include <frreport_opt.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <frlog.h>
#include <frct_comm.h>

#include "cnaps2.h"
#include "cnaps2_errcode.h"

extern void *g_p_apm_context;

extern pthread_spinlock_t g_splock_cnaps2_stmt;

extern Frhash_header *g_p_hash_cnaps2_stmt;

long l_second_4chktimeout = 0L;
long l_time_now;
#define CNAPS2_TIMEOUT_STMT   5 * 60   //单位秒

/* 格式15位是message type字符串+space+对应中文含义 */
char arr_mesg_type_maps[][80] =
{
    "hvps.111.001.01 客户发起汇兑业务",
    "hvps.112.001.01 金融机构发起汇兑业务",
    "hvps.141.001.01 即时转账",
    "hvps.142.001.01 即时转账排队/撤销通知",
    "hvps.143.001.01 PVP结算申请信息",
    "hvps.144.001.01 PVP结算应答信息",
    "hvps.151.001.01 申请清算城市商业银行汇票资金",
    "hvps.152.001.01 城市商业银行汇票全额兑付通知",
    "hvps.153.001.01 城市商业银行汇票申请退回业务",
    "hvps.154.001.01 取现回执",
    "hvps.631.001.01 多边轧差净额结算",
    "hvps.632.001.01 多边轧差净额结算清算回执",
    "hvps.633.001.01 多边轧差净额结算借贷通知",
    "hvps.634.001.01 多边净额业务撤销申请",
    "hvps.635.001.01 多边净额业务撤销应答",
    "hvps.710.001.01 大额业务对账申请",
    "hvps.711.001.01 大额业务汇总核对",
    "hvps.712.001.01 大额业务明细核对申请",
    "hvps.713.001.01 大额业务明细核对应答",
    "hvps.714.001.01 大额业务下载申请",
    "hvps.715.001.01 大额业务下载应答",
    "hvps.716.001.01 大额预对账",
    "hvps.717.001.01 资金拆借信息下载",
    "beps.121.001.01 客户发起普通贷记业务",
    "beps.122.001.01 金融机构发起普通贷记业务",
    "beps.123.001.01 实时贷记业务",
    "beps.124.001.01 实时贷记回执业务",
    "beps.125.001.01 定期贷记业务",
    "beps.127.001.01 普通借记业务",
    "beps.128.001.01 普通借记业务回执",
    "beps.130.001.01 CIS通用回执业务",
    "beps.131.001.01 实时借记业务",
    "beps.132.001.01 实时借记业务回执",
    "beps.133.001.01 定期借记业务",
    "beps.134.001.01 定期借记业务回执",
    "beps.380.001.01 批量代收业务",
    "beps.381.001.01 批量代收业务回执",
    "beps.382.001.01 批量代付业务",
    "beps.383.001.01 批量代付业务回执",
    "beps.384.001.01 实时代收业务",
    "beps.385.001.01 实时代收业务回执",
    "beps.386.001.01 实时代付业务",
    "beps.387.001.01 实时代付业务回执",
    "beps.388.001.01 代收付业务拒绝通知",
    "beps.389.001.01 代收付业务收付款确认",
    "beps.390.001.01 批量代收代付撤销申请",
    "beps.391.001.01 批量代收代付撤销应答",
    "beps.392.001.01 批量客户签约协议管理",
    "beps.393.001.01 批量客户签约协议管理应答",
    "beps.394.001.01 批量客户账户信息查询",
    "beps.395.001.01 批量客户账户查询应答",
    "beps.396.001.01 主动缴款查询",
    "beps.397.001.01 主动缴款查询应答",
    "beps.398.001.01 主动缴款通知",
    "beps.399.001.01 主动缴款通知应答",
    "beps.403.001.01 发票打印申请",
    "beps.404.001.01 发票打印回应",
    "beps.411.001.01 借记业务止付申请",
    "beps.412.001.01 借记业务止付应答",
    "beps.413.001.01 实时业务冲正申请",
    "beps.414.001.01 实时业务冲正应答",
    "beps.415.001.01 实时业务冲正通知",
    "beps.418.001.01 支票圈存管理",
    "beps.419.001.01 支票圈存管理应答",
    "beps.720.001.01 小额业务对账申请",
    "beps.721.001.01 小额业务包汇总核对",
    "beps.722.001.01 小额业务包明细核对申请",
    "beps.723.001.01 小额业务包明细核对应答",
    "beps.724.001.01 小额业务包下载申请",
    "beps.725.001.01 小额业务包下载申请应答",
    "beps.726.001.01 小额预对账",
    "nets.350.001.01 净借记限额查询申请",
    "nets.351.001.01 净借记限额查询应答",
    "nets.353.001.01 净借记限额质押/授信额度分配管理",
    "nets.354.001.01 净借记限额可用额度预警值设置",
    "nets.355.001.01 净借记限额可用额度预警通知",
    "nets.356.001.01 净借记限额管理通知",
    "saps.357.001.01 质押融资管理",
    "saps.358.001.01 人工质押融资申请",
    "saps.359.001.01 融资需要通知",
    "saps.360.001.01 筹措资金通知",
    "saps.361.001.01 清算账户余额警戒值设置申请",
    "saps.362.001.01 余额告警通知",
    "saps.363.001.01 清算排队查询申请",
    "saps.364.001.01 清算排队查询应答",
    "saps.365.001.01 清算排队管理申请",
    "saps.366.001.01 清算账户信息查询申请",
    "saps.367.001.01 清算账户信息查询应答",
    "saps.368.001.01 开户单位全面流动性查询",
    "saps.369.001.01 开户单位全面流动性应答",
    "saps.380.001.01 清算账户开户申请",
    "saps.371.001.01 清算账户维护申请",
    "saps.372.001.01 账户管理通知",
    "saps.373.001.01 清算账户资金池管理",
    "saps.374.001.01 清算账户自动拆借管理申请",
    "saps.375.001.01 清算账户自动拆借管理应答",
    "nets.376.001.01 净借记限额圈存资金调增",
    "nets.377.001.01 净借记限额圈存资金调减",
    "saps.378.001.01 质押融资债券调整通知",
    "nets.405.001.01 轧差排队查询申请",
    "nets.406.001.01 轧差排队查询应答",
    "nets.407.001.01 轧差排队管理申请",
    "saps.603.001.02 小额/网银净额清算通知",
    "saps.604.001.01 清算回执",
    "saps.606.001.01 清算账户记账通知",
    "saps.607.001.01 日间透支计息扣款通知",
    "pbcs.608.001.01 计费与返还清单",
    "saps.609.001.01 同城净额清算查询申请",
    "saps.610.001.01 同城净额清算查询应答",
    "saps.611.001.01 同城轧差净额清算业务",
    "saps.612.001.01 单边业务",
    "saps.613.001.01 错账冲正业务",
    "saps.614.001.01 资金池/自动拆借管理查询申请",
    "saps.615.001.01 资金池/自动拆借管理查询应答",
    "saps.616.001.01 非本日轧差净额清单下发",
    "nets.617.001.01 轧差净额查询请求",
    "nets.618.001.01 轧差净额查询应答",
    "saps.619.001.01 ECDS计费清单",
    "saps.730.001.01 人民银行清算业务汇总核对",
    "saps.731.001.01 人民银行清算业务明细核对申请",
    "saps.732.001.01 人民银行清算业务明细核对",
    "saps.733.001.01 人民银行（国库）日终账务数据下载",
    "saps.734.001.01 人民银行（国库）年终账户账务数据下载",
    "saps.735.001.01 账户账务明细下载",
    "saps.736.001.01 清算账户日报表下载",
    "saps.737.001.01 核对余额及工作日申请",
    "saps.738.001.01 核对余额及工作日应答",
    "saps.739.001.01 人民银行清算业务预对账",
    "saps.740.001.01 ABS账户归并申请",
    "saps.741.001.01 人民银行清算业务对账申请",
    "saps.742.001.01 日间透支信息",
    "ccms.303.001.02 自由格式",
    "ccms.307.001.02 业务撤销申请",
    "ccms.308.001.02 业务撤销应答",
    "ccms.310.001.01 通用非签名信息业务",
    "ccms.311.001.01 通用非签名信息业务应答",
    "ccms.312.001.01 通用签名信息业务",
    "ccms.313.001.01 通用签名信息业务应答",
    "ccms.314.001.01 业务查询",
    "ccms.315.001.01 业务查复",
    "ccms.316.001.01 业务状态查询申请",
    "ccms.317.001.01 业务状态查询应答",
    "ccms.318.001.01 业务退回申请",
    "ccms.319.001.01 业务退回应答",
    "ccms.801.001.02 系统状态变更通知",
    "ccms.803.001.02 参与机构状态变更通知",
    "ccms.805.001.02 登录/退出申请",
    "ccms.806.001.02 登录/退出应答",
    "ccms.807.001.02 强制离线通知",
    "ccms.809.001.02 停启运通知",
    "ccms.811.001.01 ACS专用时间结束通知",
    "ccms.900.001.02 通用处理确认",
    "ccms.903.001.02 数字证书绑定管理通知",
    "ccms.906.001.01 业务种类与类型管理",
    "ccms.907.001.02 系统参数变更",
    "ccms.911.001.02 丢弃通知",
    "ccms.913.001.01 CIS代理行变更通知",
    "ccms.915.001.01 业务权限变更通知",
    "ccms.916.001.01 行名行号变更通知",
    "ccms.917.001.01 基础信息变更通知",
    "ccms.919.001.01 数字证书下载申请",
    "ccms.921.001.01 数字证书下载应答",
    "ccms.926.001.01 业务金额上限下发",
    "ccms.990.001.02 通信级确认",
    "ccms.991.001.01 探测请求",
    "ccms.992.001.01 探测回应",
    // 网上支付跨行清算系统报文交换标准
    "ibps.101.001.01 网银贷记业务",
    "ibps.102.001.01 网银贷记业务回执",
    "ibps.103.001.01 网银借记业务",
    "ibps.104.001.01 网银借记业务回执",
    "ibps.105.001.01 第三方贷记业务",
    "ibps.106.001.01 第三方贷记业务回执",
    "ccms.303.001.01 自由格式",
    "ibps.305.001.01 业务状态查询",
    "ibps.306.001.01 业务状态查询应答",
    "ibps.307.001.01 业务撤销申请",
    "ibps.308.001.01 业务撤销应答",
    "ibps.309.001.01 账户余额查询申请",
    "ibps.310.001.01 账户余额查询应答",
    "ibps.311.001.01 账户交易明细查询申请",
    "ibps.312.001.01 账户交易明细查询应答",
    "ibps.331.001.01 预授权申请",
    "ibps.332.001.01 预授权应答",
    "ibps.333.001.01 预授权撤销申请",
    "ibps.334.001.01 预授权撤销应答",
    "ibps.335.001.01 授权支付协议管理申请",
    "ibps.336.001.01 授权支付协议管理应答",
    "ibps.337.001.01 授权支付协议管理通知",
    "ibps.338.001.01 授权支付协议管理通知应答",
    "ibps.339.001.01 账户信息查询协议管理申请",
    "ibps.340.001.01 账户信息查询协议管理应答",
    "ibps.341.001.01 账户信息查询协议管理通知",
    "ibps.342.001.01 账户信息查询协议管理通知应答",
    "saps.601.001.01 轧差通知",
    "saps.603.001.01 清算通知",
    "saps.605.001.01 计费与返还清单",
    "ibps.701.001.01 汇总核对",
    "ibps.703.001.01 业务明细核对申请",
    "ibps.704.001.01 业务明细核对应答",
    "ibps.705.001.01 业务明细核对下载申请",
    "ibps.706.001.01 业务明细核对下载应答",
    "ccms.801.001.01 系统状态变更通知",
    "ccms.803.001.01 参与机构状态变更通知",
    "ccms.805.001.01 登录/退出申请",
    "ccms.806.001.01 登录/退出应答",
    "ccms.807.001.01 强制离线通知",
    "ccms.809.001.01 停运通知",
    "ccms.900.001.01 通用处理确认",
    "ibps.901.001.01 行别变更通知",
    "ccms.903.001.01 数字证书绑定通知",
    "ccms.905.001.01 参与机构变更通知",
    "ccms.907.001.01 系统参数变更通知",
    "ccms.909.001.01 支付业务金额上限变更通知",
    "ccms.911.001.01 丢弃通知",
    "ccms.990.001.01 通信级确认",
};

char arr_mesg_resp[][16] = {
    "hvps.144.001.01",
    "hvps.154.001.01",
    "hvps.632.001.01",
    "hvps.635.001.01",
    "hvps.713.001.01",
    "hvps.715.001.01",
    "beps.124.001.01",
    "beps.128.001.01",
    "beps.130.001.01",
    "beps.132.001.01",
    "beps.134.001.01",
    "beps.381.001.01",
    "beps.383.001.01",
    "beps.385.001.01",
    "beps.387.001.01",
    "beps.389.001.01",
    "beps.391.001.01",
    "beps.393.001.01",
    "beps.395.001.01",
    "beps.397.001.01",
    "beps.399.001.01",
    "beps.404.001.01",
    "beps.412.001.01",
    "beps.414.001.01",
    "beps.419.001.01",
    "beps.723.001.01",
    "beps.725.001.01",
    "nets.351.001.01",
    "saps.364.001.01",
    "saps.367.001.01",
    "saps.369.001.01",
    "saps.375.001.01",
    "nets.406.001.01",
    "saps.610.001.01",
    "saps.615.001.01",
    "nets.618.001.01",
    "ccms.308.001.02",
    "ccms.311.001.01",
    "ccms.313.001.01",
    "ccms.315.001.01",
    "ccms.317.001.01",
    "ccms.319.001.01",
    "ccms.806.001.02",
//    "ccms.900.001.02",
    "ccms.921.001.01",
    "ccms.990.001.02",
    "ccms.992.001.01",
    // 网上支付跨行清算系统报文交换标准
    "ibps.102.001.01",
    "ibps.104.001.01",
    "ibps.106.001.01",
    "ibps.306.001.01",
    "ibps.308.001.01",
    "ibps.310.001.01",
    "ibps.312.001.01",
    "ibps.332.001.01",
    "ibps.334.001.01",
    "ibps.336.001.01",
    "ibps.338.001.01",
    "ibps.340.001.01",
    "ibps.342.001.01",
    "ibps.704.001.01",
    "ibps.706.001.01",
    "ccms.806.001.01",
    "ccms.990.001.01",
};

void cnaps2_mesg_type_quicksort(int i_start
                                , int i_right)
{
    if (i_right == -1)
        i_right = sizeof(arr_mesg_type_maps) / sizeof(arr_mesg_type_maps[0]) - 1;
    int i_min = i_start;
    int i_max = i_right;
    int i_left = i_start;
    char arr_tmp[sizeof(arr_mesg_type_maps[0])] = {0};
    strcpy(arr_tmp, arr_mesg_type_maps[i_start]);

    while (i_min < i_max)
    {
//        printf("arr_mesg_type_maps[i_max]:[%s]\n", arr_mesg_type_maps[i_max]);
//        printf("arr_tmp:[%s]\n\n", arr_tmp);
        while (strncmp(arr_mesg_type_maps[i_max], arr_tmp, 15) >= 0 && i_max >= i_left)
            i_max--;

        if (i_max > i_left)
        {
            strcpy(arr_mesg_type_maps[i_left], arr_mesg_type_maps[i_max]);
            i_left = i_max;
        }

        while (strncmp(arr_mesg_type_maps[i_min], arr_tmp, 15) <= 0 && i_min <= i_left)
            i_min++;

        if (i_min < i_left)
        {
            strcpy(arr_mesg_type_maps[i_left], arr_mesg_type_maps[i_min]);
            i_left = i_min;
        }
    }

    strcpy(arr_mesg_type_maps[i_left], arr_tmp);
    if(i_left - i_start > 1)
        cnaps2_mesg_type_quicksort(i_start, i_left - 1);
    if(i_right - i_left > 1)
        cnaps2_mesg_type_quicksort(i_left + 1, i_right);
    return;
}

void cnaps2_mesg_resp_quicksort(int i_start
                                , int i_right)
{
    if (i_right == -1)
        i_right = sizeof(arr_mesg_resp) / sizeof(arr_mesg_resp[0]) - 1;
    int i_min = i_start;
    int i_max = i_right;
    int i_left = i_start;
    char arr_tmp[sizeof(arr_mesg_resp[0])] = {0};
    strcpy(arr_tmp, arr_mesg_resp[i_start]);

    while (i_min < i_max)
    {
        while (strcmp(arr_mesg_resp[i_max], arr_tmp) >= 0 && i_max >= i_left)
            i_max--;

        if (i_max > i_left)
        {
            strcpy(arr_mesg_resp[i_left], arr_mesg_resp[i_max]);
            i_left = i_max;
        }

        while (strcmp(arr_mesg_resp[i_min], arr_tmp) <= 0 && i_min <= i_left)
            i_min++;

        if (i_min < i_left)
        {
            strcpy(arr_mesg_resp[i_left], arr_mesg_resp[i_min]);
            i_left = i_min;
        }
    }

    strcpy(arr_mesg_resp[i_left], arr_tmp);
    if(i_left - i_start > 1)
        cnaps2_mesg_resp_quicksort(i_start, i_left - 1);
    if(i_right - i_left > 1)
        cnaps2_mesg_resp_quicksort(i_left + 1, i_right);
    return;
}

/*******************************************************************************
*  FUNC     :  取得报文编码对应的中文含义
*  ARGS     :  i_start (开始位置)
*           :  i_right (结束位置)
*  RTN      :  中文含义
*  NOTE     :
*******************************************************************************/
FR_STATIC void __cnaps2_mesg_type_to_cn(char *p_mesg_type
                                        , char *p_mesg_type_cn)
{
    int i_low = 0;
    int i_high = sizeof(arr_mesg_type_maps) / sizeof(arr_mesg_type_maps[0]) - 1;
    int i_mid = 0;
    char *p_acl = NULL;
    int i_ret = 0;

    while (i_low < i_high)
    {
        i_mid = (i_low + i_high) / 2;

        i_ret = strncmp(arr_mesg_type_maps[i_mid], p_mesg_type, 15);
        if (i_ret == 0)
        {
            p_acl = arr_mesg_type_maps[i_mid];
            break;
        }
        else if (i_ret > 0)
            i_high = i_mid;
        else
            i_low = i_mid + 1;
    }

    if (p_acl == NULL)
        strncpy(p_mesg_type_cn, p_mesg_type, strlen(p_mesg_type));
    else
    {
        p_acl += 16;
        strncpy(p_mesg_type_cn, p_acl, strlen(p_acl));
    }
    return;
}

/*******************************************************************************
*  FUNC     :  根据报文编码判断是否是响应
*  ARGS     :  i_start (开始位置)
*           :  i_right (结束位置)
*  RTN      :  中文含义
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_mesg_is_resp(char *p_mesg_type)
{
    int i_low = 0;
    int i_high = sizeof(arr_mesg_resp) / sizeof(arr_mesg_resp[0]) - 1;
    int i_mid = 0;
    int i_ret = 0;

    while (i_low < i_high)
    {
        i_mid = (i_low + i_high) / 2;

        i_ret = strcmp(arr_mesg_resp[i_mid], p_mesg_type);
        if (i_ret == 0)
            return FR_YES;
        else if (i_ret > 0)
            i_high = i_mid;
        else
            i_low = i_mid + 1;
    }

    return FR_NO;
}

/*******************************************************************************
*  FUNC     :  用二分法查找 arr_cnaps2_syscode_maps
*  ARGS     :  key                                  (charset编号)
*  RTN      :  -1                                   (未找到)
*              index                                (找到的下标)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_get_syscode_index(unsigned int key)
{
    int len = sizeof(arr_cnaps2_syscode_maps) / sizeof(arr_cnaps2_syscode_maps[0]);
    int mid = 0;
    int front = 0;
    int back = len - 1;
    while (front <= back)
    {
        mid = (front + back) / 2;
        if (arr_cnaps2_syscode_maps[mid].ui_code == key)
            return mid;
        if (arr_cnaps2_syscode_maps[mid].ui_code < key)
            front = mid + 1;
        else
            back = mid - 1;
    }
    return -1;
}

/*******************************************************************************
*  FUNC     :  用二分法查找 arr_cnaps2_nodecode_maps
*  ARGS     :  key                                  (charset编号)
*  RTN      :  -1                                   (未找到)
*              index                                (找到的下标)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_get_nodecode_index(unsigned int key)
{
    int len = sizeof(arr_cnaps2_nodecode_maps) / sizeof(arr_cnaps2_nodecode_maps[0]);
    int mid = 0;
    int front = 0;
    int back = len - 1;
    while (front <= back)
    {
        mid = (front + back) / 2;
        if (arr_cnaps2_nodecode_maps[mid].ui_code == key)
            return mid;
        if (arr_cnaps2_nodecode_maps[mid].ui_code < key)
            front = mid + 1;
        else
            back = mid - 1;
    }
    return -1;
}

/*******************************************************************************
*  FUNC     :  用二分法查找 arr_cnaps2_prccode_maps
*  ARGS     :  key                                  (charset编号)
*  RTN      :  -1                                   (未找到)
*              index                                (找到的下标)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_get_prccode_index(long long key)
{
    int len = sizeof(arr_cnaps2_prccode_maps) / sizeof(arr_cnaps2_prccode_maps[0]);
    int mid = 0;
    int front = 0;
    int back = len - 1;
    while (front <= back)
    {
        mid = (front + back) / 2;
        if (arr_cnaps2_prccode_maps[mid].ll_code == key)
            return mid;
        if (arr_cnaps2_prccode_maps[mid].ll_code < key)
            front = mid + 1;
        else
            back = mid - 1;
    }
    return -1;
}

/*!
 * 将 I0000 转换为 0x4930303030
 *
 * \param p_string                      (I0000)
 * \param ui_string_len                (字符串长度)
 *
 * \return 转换后的十六进制值
 *
 */
FR_STATIC long long __cnaps2_string_to_hexll(char *p_string
                                            , unsigned int ui_string_len)
{
    unsigned int ui_loop = 0;
    long long ll_value = 0LL;
    while (ui_loop < ui_string_len)
    {
        ll_value = *(p_string + ui_loop) + (ll_value << 8);
        ui_loop++;
    }
    return ll_value;
}

/*!
 * 将 "PM1I0000"的形式 转换为 "PM1I0000:支付报文传输平台-NPC开放系统-处理成功"的形式
 *
 * \param p_resp_code                   (PM1I0000)
 * \param p_resp_codestring             (存放转换后字符串的buffer)
 * \param resp_codestring_len           (存放转换后字符串的buffer长度)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int __cnaps2_convert_resp_code(char *p_resp_code
                                        , char *p_resp_codestring
                                        , size_t resp_codestring_len)
{
    short *p_s_syscode;
    short s_syscode;
    int i_syscode_map_index;
    char c_nodecode;
    int i_nodecode_map_index;
    long long ll_prccode;
    int i_prccode_map_index;

    if (p_resp_code == NULL || strlen(p_resp_code) != 8)
        return FR_FAIL;

    p_s_syscode = (short *) p_resp_code;
    s_syscode = ntohs(*p_s_syscode);
    if ((i_syscode_map_index = __cnaps2_get_syscode_index((unsigned int) s_syscode)) == -1)
        return FR_FAIL;

    c_nodecode = *(p_resp_code + 2);
    if ((i_nodecode_map_index = __cnaps2_get_nodecode_index((unsigned int) c_nodecode)) == -1)
        return FR_FAIL;

    ll_prccode = __cnaps2_string_to_hexll(p_resp_code + 3, strlen(p_resp_code + 3));
    if ((i_prccode_map_index = __cnaps2_get_prccode_index(ll_prccode)) == -1)
        return FR_FAIL;

    snprintf(p_resp_codestring, resp_codestring_len, "%s:%s-%s-%s",
             p_resp_code,
             arr_cnaps2_syscode_maps[i_syscode_map_index].arr_name,
             arr_cnaps2_nodecode_maps[i_nodecode_map_index].arr_name,
             arr_cnaps2_prccode_maps[i_prccode_map_index].arr_name
    );

    return FR_SUCC;
}

/*!
 * 释放内存
 *
 * \param pp_buffer (需要释放的双重指针)
 *
 * \return void
 *
 */
FR_STATIC void cnaps2_free(void **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
        return;

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*!
 * 替换原有的L7指标项
 *
 * \param p_st_report_data  (数据上报结构体)
 * \param p_key             (键)
 * \param p_value           (值)
 *
 * \return 0  失败\n
 *         1  成功
 *

FR_STATIC int FrReportOpt_replace_string(Frreport_data *p_st_report_data
                                        , const char *p_key
                                        , const char *p_value)
{
    FrReportOpt_del_fieldAll(p_st_report_data, p_key);
    if (FrReportOpt_add_fieldStr(p_st_report_data, p_key, p_value) == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}
*/

/*!
 * 替换原有的L7指标项
 *
 * \param p_st_report_data  (数据上报结构体)
 * \param p_key             (键)
 * \param l_value           (值)
 *
 * \return 0  失败\n
 *         1  成功
 *

FR_STATIC int FrReportOpt_replace_long(Frreport_data *p_st_report_data
                                        , const char *p_key
                                        , long l_value)
{
    FrReportOpt_del_fieldAll(p_st_report_data, p_key);
    if (FrReportOpt_add_fieldLong(p_st_report_data, p_key, l_value) == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}
*/

/*******************************************************************************
*  FUNC     :  时间格式化成 2015-03-29 22:25:12.448671 的格式
*  ARGS     :  *p_tv                           (时间戳)
*           :  *p_time                         (buffer)
*           :  ui_time_size                    (buffer size)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_frtime2datetimestr(struct timeval *p_tv
        , char *p_time
        , unsigned int ui_time_size)
{
    struct tm *p_tm = NULL;

    if(p_tv == NULL || p_time == NULL || ui_time_size <= 1)
        return FR_FAIL;

    p_tm = localtime(&(p_tv->tv_sec));

    snprintf(p_time,ui_time_size,"%04d-%02d-%02d %02d:%02d:%02d.%06ld",
             p_tm->tm_year + 1900,p_tm->tm_mon + 1,p_tm->tm_mday,
             p_tm->tm_hour,p_tm->tm_min,p_tm->tm_sec,p_tv->tv_usec);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  打印时间
*  ARGS     :  st_timestamp                         (时间戳)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void cnaps2_print_timeval(struct timeval st_timestamp)
{
    char arr_buff[64];
    __cnaps2_frtime2datetimestr(&st_timestamp, arr_buff, sizeof(arr_buff));
    printf(":[%s]\n", arr_buff);
}

/*******************************************************************************
*  FUNC     :  按一个字节打印十六进行字符串
*  ARGS     :  *p_buff  (char*字符串)
*           :  i_len   (字符串长度)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void __print_hex_string(char *p_buff, int i_len)
{
    int i_loop;

    for (i_loop = 0; i_loop < i_len; i_loop++)
    {
        printf("%02x", p_buff[i_loop] & 0xFF);
    }

    return;
}

void cnaps2_stmt_free(L7_cnaps2_stmt **pp_cnaps2_stmt)
{
    if (pp_cnaps2_stmt == NULL || *pp_cnaps2_stmt == NULL)
        return;

    L7_cnaps2_stmt *p_st_cnaps2_stmt = *pp_cnaps2_stmt;
    frreport_body_l7list_free(&(p_st_cnaps2_stmt->p_report_comm));
    frreport_body_l7list_free(&(p_st_cnaps2_stmt->p_report_req));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_req_mesg_type));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_req_mesg_type_cn));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_req_mesg_id));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_req_mesg_ref_id));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_mesg_type));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_mesg_type_cn));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_mesg_id));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_mesg_ref_id));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_code));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_codestring));
    cnaps2_free((void **) &(p_st_cnaps2_stmt->p_resp_mq_message));
    cnaps2_free((void **) pp_cnaps2_stmt);

    return;
}

void cnaps2_stmt_node_free(Frlist_node *p_st_node)
{
    if (p_st_node == NULL || p_st_node->data == NULL)
        return;

    L7_cnaps2_stmt *p_st_cnaps2_stmt = (L7_cnaps2_stmt *) FRLIST_GET_NODE_DATA(p_st_node);
//    if (p_st_cnaps2_stmt->p_req_mesg_type_cn)
//        CNAPS2_PRINT_WARN("free p_req_mesg_type_cn:[%s]\n", p_st_cnaps2_stmt->p_req_mesg_type_cn);
//    if (p_st_cnaps2_stmt->p_resp_mesg_ref_id)
//        CNAPS2_PRINT_WARN("free p_resp_mesg_ref_id:[%s]\n", p_st_cnaps2_stmt->p_resp_mesg_ref_id);
    cnaps2_stmt_free(&p_st_cnaps2_stmt);
    p_st_node->data = NULL;

    return;
}

FR_STATIC int __check_timeout_stmt(Frlist_node* p_st_node, const void *p_data)
{
    L7_cnaps2_stmt *p_cnaps2_stmt = NULL;
    Frhash_header *p_hash_stmt = (Frhash_header *) p_data;

    p_cnaps2_stmt = (L7_cnaps2_stmt *) FRLIST_GET_NODE_DATA(p_st_node);

    if (p_cnaps2_stmt == NULL)
        return 1;

    if (l_time_now - p_cnaps2_stmt->l_stmt_time >= CNAPS2_TIMEOUT_STMT)
    {
        if (p_cnaps2_stmt->p_req_mesg_type_cn)
            CNAPS2_PRINT_INFO("del timeouted stmt req:[%s] id:[%s] ref_id:[%s]\n", p_cnaps2_stmt->p_req_mesg_type_cn, p_cnaps2_stmt->p_req_mesg_id, p_cnaps2_stmt->p_req_mesg_ref_id);
        else if (p_cnaps2_stmt->p_resp_mesg_type_cn)
            CNAPS2_PRINT_WARN("del timeouted stmt resp:[%s] id:[%s] ref_id:[%s]\n", p_cnaps2_stmt->p_resp_mesg_type_cn, p_cnaps2_stmt->p_resp_mesg_id, p_cnaps2_stmt->p_resp_mesg_ref_id);
        frhash2_del(p_hash_stmt, p_st_node, cnaps2_stmt_node_free);
        return 1;
    }

    return 1;
}

FR_STATIC void __clear_timeout_stmt()
{
    struct timeval tv;

    pthread_spin_lock(&g_splock_cnaps2_stmt);

    gettimeofday(&tv, NULL);
    long l_second_now = tv.tv_sec;

    if (l_second_4chktimeout == 0L)
    {
        l_second_4chktimeout = l_second_now;
        CNAPS2_PRINT_INFO("init l_second_4chktimeout=[%ld]\n", l_second_4chktimeout);
        pthread_spin_unlock(&g_splock_cnaps2_stmt);
        return;
    }
    else if (l_second_now - l_second_4chktimeout < CNAPS2_TIMEOUT_STMT)
    {
        CNAPS2_PRINT_INFO("check l_second_now - l_second_4chktimeout = %ld < %d\n", l_second_now - l_second_4chktimeout, CNAPS2_TIMEOUT_STMT);
        pthread_spin_unlock(&g_splock_cnaps2_stmt);
        return;
    }
    else
        l_second_4chktimeout = l_second_now;

    CNAPS2_PRINT_INFO("start to check timeouted stmt...\n");
    l_time_now = l_second_now;
    frhash2_run(g_p_hash_cnaps2_stmt, g_p_hash_cnaps2_stmt, __check_timeout_stmt);
    pthread_spin_unlock(&g_splock_cnaps2_stmt);
    CNAPS2_PRINT_INFO("stop to check timeouted stmt...\n");

    return;
}

FR_STATIC int __cnaps2_put_report_stmt(const char *p_key
                                    , unsigned int ui_key_len
                                    , L7_cnaps2_stmt **pp_cnaps2_stmt)
{
    Frlist_node *p_st_node = NULL;
    struct timeval tv;

    if (p_key == NULL || ui_key_len <= 0)
        return FR_FAIL;

    gettimeofday(&tv, NULL);
    (*pp_cnaps2_stmt)->l_stmt_time = tv.tv_sec;

    pthread_spin_lock(&g_splock_cnaps2_stmt);

    p_st_node = frlist_node_create(*pp_cnaps2_stmt);
    if (frhash2_addStr(g_p_hash_cnaps2_stmt, p_key, ui_key_len, p_st_node) != FR_SUCC)
    {
        pthread_spin_unlock(&g_splock_cnaps2_stmt);
        goto error;
    }
    *pp_cnaps2_stmt = NULL;

    pthread_spin_unlock(&g_splock_cnaps2_stmt);

    return FR_SUCC;
error:
    cnaps2_stmt_free(pp_cnaps2_stmt);
    cnaps2_stmt_node_free(p_st_node);
    return FR_FAIL;
}

FR_STATIC L7_cnaps2_stmt *__cnaps2_get_report_stmt(const char *p_key
                                                    , unsigned int ui_key_len)
{
    Frlist_node *p_st_node = NULL;
    L7_cnaps2_stmt *p_cnaps2_stmt = NULL;

    if (p_key == NULL || ui_key_len <= 0)
        return NULL;

    pthread_spin_lock(&g_splock_cnaps2_stmt);
    if ((p_st_node = frhash2_getStr(g_p_hash_cnaps2_stmt, p_key, ui_key_len)) == NULL)
    {
        pthread_spin_unlock(&g_splock_cnaps2_stmt);
        return NULL;
    }

    frhash2_apart(g_p_hash_cnaps2_stmt, p_st_node);
    pthread_spin_unlock(&g_splock_cnaps2_stmt);

    p_cnaps2_stmt = (L7_cnaps2_stmt *) FRLIST_GET_NODE_DATA(p_st_node);
    frlist_node_free2(&p_st_node);

    return p_cnaps2_stmt;
}

/*!
 * 检测是否为CNAPS2协议
 *
 * \param p_payload         (解析用数据)
 * \param i_payload_len     (数据长度)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int __cnaps2_detect(const char *p_payload
                                , const size_t i_payload_len)
{
    CNAPS2_PRINT_INFO("__cnaps2_detect...\n");
    if (i_payload_len > CNAPS2_H_HEADER_LEN - 4 &&
        strncmp(p_payload, CNAPS2_H_HEADER_BEGIN, strlen(CNAPS2_H_HEADER_BEGIN)) == 0 &&
        strncmp(p_payload + CNAPS2_VERSIONID_OFFSET, CNAPS2_VERSION1, strlen(CNAPS2_VERSION1)) == 0 &&
        strncmp(p_payload + CNAPS2_H_HEADER_END_OFFSET - 4, CNAPS2_HEADER_END, strlen(CNAPS2_HEADER_END)) == 0)
    {
        CNAPS2_PRINT_WARN("CNAPS2_IS_H_V1\n");
        return CNAPS2_IS_H_V1;
    }
    else if (i_payload_len > CNAPS2_H_HEADER_LEN &&
        strncmp(p_payload, CNAPS2_H_HEADER_BEGIN, strlen(CNAPS2_H_HEADER_BEGIN)) == 0 &&
        strncmp(p_payload + CNAPS2_VERSIONID_OFFSET, CNAPS2_VERSION2, strlen(CNAPS2_VERSION2)) == 0 &&
        strncmp(p_payload + CNAPS2_H_HEADER_END_OFFSET, CNAPS2_HEADER_END, strlen(CNAPS2_HEADER_END)) == 0)
    {
        CNAPS2_PRINT_WARN("CNAPS2_IS_H_V2\n");
        return CNAPS2_IS_H_V2;
    }
    else if (i_payload_len > CNAPS2_U_HEADER_LEN &&
        strncmp(p_payload, CNAPS2_U_HEADER_BEGIN, strlen(CNAPS2_U_HEADER_BEGIN)) == 0 &&
        (strncmp(p_payload + CNAPS2_VERSIONID_OFFSET, CNAPS2_VERSION1, strlen(CNAPS2_VERSION1)) == 0 ||
        strncmp(p_payload + CNAPS2_VERSIONID_OFFSET, CNAPS2_VERSION2, strlen(CNAPS2_VERSION2)) == 0) &&
        strncmp(p_payload + CNAPS2_U_HEADER_END_OFFSET, CNAPS2_HEADER_END, strlen(CNAPS2_HEADER_END)) == 0)
    {
        CNAPS2_PRINT_WARN("CNAPS2_IS_U\n");
        return CNAPS2_IS_U;
    }
    else
        return CNAPS2_IS_FAIL;
}

/*!
 * 解析CNAPS2报文头
 *
 * \param p_payload          (解析用数据)
 * \param p_req_mesg_type    (报文类型)
 * \param p_mesg_id          (通信级标识号)
 * \param p_mesg_ref_id      (通信级参考号)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int __cnaps2_parse_header(const char *p_payload
                                    , char *p_mesg_type
                                    , char *p_mesg_id
                                    , char *p_mesg_ref_id
                                    , int i_cnaps2_version)
{
    CNAPS2_PRINT_INFO("__cnaps2_parse_header...\n");
    if (i_cnaps2_version == CNAPS2_IS_U)
    {
        if (strncmp(p_payload + CNAPS2_U_HEADER_STRUCT_TYPE_OFFSET, "XML", CNAPS2_HEADER_STRUCT_TYPE_LEN) != 0)
            return FR_FAIL;

        strncpy(p_mesg_type, p_payload + CNAPS2_U_HEADER_MESG_TYPE_OFFSET, CNAPS2_HEADER_MESG_TYPE_LEN);
        strncpy(p_mesg_id, p_payload + CNAPS2_U_HEADER_MESG_ID_OFFSET, CNAPS2_HEADER_MESG_ID_LEN);
        strncpy(p_mesg_ref_id, p_payload + CNAPS2_U_HEADER_MESG_REF_ID_OFFSET, CNAPS2_HEADER_MESG_REF_ID_LEN);
    }
    else
    {
        if (strncmp(p_payload + CNAPS2_H_HEADER_STRUCT_TYPE_OFFSET - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0), "XML", CNAPS2_HEADER_STRUCT_TYPE_LEN) != 0)
            return FR_FAIL;

        strncpy(p_mesg_type, p_payload + CNAPS2_H_HEADER_MESG_TYPE_OFFSET - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0), CNAPS2_HEADER_MESG_TYPE_LEN);
        strncpy(p_mesg_id, p_payload + CNAPS2_H_HEADER_MESG_ID_OFFSET - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0), CNAPS2_HEADER_MESG_ID_LEN);
        strncpy(p_mesg_ref_id, p_payload + CNAPS2_H_HEADER_MESG_REF_ID_OFFSET - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0), CNAPS2_HEADER_MESG_REF_ID_LEN);
    }
    frtrim(p_mesg_type);
    frtrim(p_mesg_id);
    frtrim(p_mesg_ref_id);

#if APM_CNAPS2_DBG
    if (strlen(p_mesg_type) == 0)
        CNAPS2_PRINT_ALERT("p_mesg_type == 0\n");
    if (strlen(p_mesg_id) == 0)
        CNAPS2_PRINT_ALERT("p_mesg_id == 0\n");
    if (strlen(p_mesg_ref_id) == 0)
        CNAPS2_PRINT_ALERT("p_mesg_ref_id == 0\n");
#endif

    if (strlen(p_mesg_type) == 0 || strlen(p_mesg_id) == 0 || strlen(p_mesg_ref_id) == 0)
        return FR_FAIL;

    CNAPS2_PRINT_INFO("__cnaps2_parse_header success...\n");
    return FR_SUCC;
}

/*!
 * 跳过数字签名域
 *
 * \param p_payload             (解析用数据)
 * \param p_ui_mesg_body_offset (报文体下标位置)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int __cnaps2_skip_digital_signature(char *p_payload
                                            , unsigned int *p_ui_mesg_body_offset
                                            , int i_cnaps2_version)
{
    char *p_payload_without_header = NULL;

    if (i_cnaps2_version == CNAPS2_IS_U)
    {
        *p_ui_mesg_body_offset = (unsigned int) CNAPS2_U_HEADER_LEN;
        p_payload_without_header = p_payload + CNAPS2_U_HEADER_LEN;
    }
    else
    {
        *p_ui_mesg_body_offset = (unsigned int) CNAPS2_H_HEADER_LEN - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0);
        p_payload_without_header = p_payload + CNAPS2_H_HEADER_LEN - (i_cnaps2_version == CNAPS2_IS_H_V1 ? 4 : 0);
    }

    if (strncmp(p_payload_without_header, CNAPS2_SIGNATURE_BEGIN, strlen(CNAPS2_SIGNATURE_BEGIN)) == 0)
    {
        char *p_end = NULL;
        if ((p_end = strstr((char *)p_payload_without_header, CNAPS2_SIGNATURE_END)))
            *p_ui_mesg_body_offset += (unsigned int) (p_end - p_payload_without_header) + strlen(CNAPS2_SIGNATURE_END);
        else
            return FR_FAIL;
    }

    return FR_SUCC;
}

/*!
 * 获取node节点的内容
 *
 * \param xpathCtx          (xpath上下文)
 * \param xpathExpr         (xmlChar)
 * \param pp_value          (获取到的内容)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int cnaps2_parse_xml_get_text(xmlXPathContextPtr xpathCtx
                                        , xmlChar *xpathExpr
                                        , char **pp_value)
{
    xmlXPathObjectPtr xpathObj = NULL;
    xmlChar *p_value = NULL;

    if ((xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx)) == NULL)
        goto error;

    if (xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
        goto success;

    if (xpathObj->nodesetval->nodeTab[0]->type == XML_ELEMENT_NODE)
    {
        cnaps2_free((void **) pp_value);
        if ((p_value = xmlNodeGetContent(xpathObj->nodesetval->nodeTab[0])))
        {
            *pp_value = frstrdup((const char *) p_value);
            xmlFree(p_value);
        }
        else
            *pp_value = NULL;
    }
    else
        goto error;

success:
    xmlXPathFreeObject(xpathObj);
    return FR_SUCC;
error:
    if (xpathObj)
        xmlXPathFreeObject(xpathObj);
    return FR_FAIL;
}

/*!
 * 解析XML
 *
 * \param p_payload           (解析用数据)
 * \param i_payload_len       (数据长度)
 * \param pp_resp_code        (PM1I0000)
 * \param pp_resp_codestring  (RjctInf内容)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
FR_STATIC int cnaps2_parse_xml(const char *p_payload
                            , const int i_payload_len
                            , char **pp_resp_code
                            , char **pp_resp_codestring)
{
    xmlDocPtr doc = NULL;
    xmlNodePtr p_st_root = NULL;
    xmlXPathContextPtr xpathCtx = NULL;
    char *p_resp_code = NULL;
    char *p_resp_codestring = NULL;

    if (i_payload_len < 5 || strncmp(p_payload, "<?xml", 5) != 0)
        return FR_SUCC;

    if ((doc = xmlReadMemory(p_payload, i_payload_len, NULL, NULL, 0)) == NULL)
        goto error;

    if ((p_st_root = xmlDocGetRootElement(doc)) == NULL)
        goto error;

    if (p_st_root->name == NULL || strcmp((const char *) p_st_root->name, "Document") != 0)
        goto error;

    if ((xpathCtx = xmlXPathNewContext(doc)) == NULL)
        goto error;

    // 业务应答信息组件 .//RspnInf/RjctCd .//RspnInf/RjctInf
    // NPC处理信息组件 .//NPCPrcInf/PrcCd .//NPCPrcInf/RjctInf
    // 登录/退出应答报文 .//LoginRspnInf/PrcCd .//LoginRspnInf/RjctInf
    // 通用处理确认报文 .//CmonConfInf/PrcCd .//CmonConfInf/RjctInf
    // 报文丢弃通知报文 .//DscrdInf/PrcCd .//DscrdInf/RjctInf
    if (p_resp_code == NULL && cnaps2_parse_xml_get_text(xpathCtx, BAD_CAST "//*[local-name()='RjctCd']", &p_resp_code) == FR_FAIL)
        goto error;
    if (p_resp_code == NULL && cnaps2_parse_xml_get_text(xpathCtx, BAD_CAST "//*[local-name()='PrcCd']", &p_resp_code) == FR_FAIL)
        goto error;
    if (cnaps2_parse_xml_get_text(xpathCtx, BAD_CAST "//*[local-name()='RjctInf']", &p_resp_codestring) == FR_FAIL)
        goto error;

    // 通信级确认报文 .//ConfInf/MsgPrcCd
    if (p_resp_code == NULL && cnaps2_parse_xml_get_text(xpathCtx, BAD_CAST "//*[local-name()='MsgPrcCd']", &p_resp_code) == FR_FAIL)
        goto error;

    *pp_resp_code = p_resp_code;
    *pp_resp_codestring = p_resp_codestring;

    xmlXPathFreeContext(xpathCtx);
    xmlFreeDoc(doc);
    return FR_SUCC;
error:
    cnaps2_free((void **) &p_resp_code);
    cnaps2_free((void **) &p_resp_codestring);
    if (xpathCtx)
        xmlXPathFreeContext(xpathCtx);
    if (doc)
        xmlFreeDoc(doc);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  按 PM1I0000 编码中的第四位判断，O和S表示错误，其他正确
*  ARGS     :  p_resp_code                              (PM1I0000)
*  RTN      :  0
*              -1
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_resp_code_short(char *p_resp_code)
{
    char c_code_type = 0;
    if (p_resp_code == NULL)
        return 0;

    // XXX: 出现4位的response code
    if (strlen(p_resp_code) == 4)
        return (strcmp(p_resp_code, "0000") == 0) ? 0 : -1;

    if (strlen(p_resp_code) != 8)
        return -1;
    c_code_type = *(p_resp_code + 3);
    return (c_code_type == 'O' || c_code_type == 'S') ? -1 : 0;
}

FR_STATIC int __cnaps2_report_req(Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , L7_cnaps2_stmt *p_cnaps2_stmt
                                , long long ll_req_start_timestamp
                                , long long ll_req_end_timestamp
                                , long long ll_send_time
                                , long long ll_data_bytes
                                , char *p_title
                                , char *p_mesg_type
                                , char *p_mesg_type_cn
                                , char *p_mesg_id
                                , char *p_mesg_ref_id
                                , char *p_mq_message)
{
    CNAPS2_PRINT_WARN("__cnaps2_report_req...\n");
    Frreport_body_data *p_st_body = NULL;
    Frreport_data *p_st_report_data = NULL;

    if ((p_st_body = frreport_body_new_l7(p_st_conn)) == NULL)
        goto error;
    if (frreport_body_l7_add_connInfo(p_st_body, p_st_conn) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_ulong(p_st_body, APM_REPORT_KEY_REQ_ID, frct_seq_increase(p_st_conn)) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_int(p_st_body, APM_REPORT_KEY_REQ_ISRESPREQUIRED, FR_YES) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_REQ_START_TIMESTAMP, ll_req_start_timestamp) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_REQ_END_TIMESTAMP, ll_req_end_timestamp) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_REQ_SEND_TIME_US, ll_send_time) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_REQ_DATA_BYTES, ll_data_bytes) != FR_SUCC)
        goto error;
    if (p_title && frreport_body_l7_add_str(p_st_body, APM_REPORT_KEY_TRANS_TITLE, p_title) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "transaction.type_code", p_mesg_type) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "transaction.type_name", p_mesg_type_cn) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "request.cnaps2.mesg_id", p_mesg_id) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "request.cnaps2.mesg_ref_id", p_mesg_ref_id) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "request.cnaps2.mesg", p_mq_message) == FR_FAIL)
        goto error;

    p_cnaps2_stmt->p_report_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_body);
    p_cnaps2_stmt->p_report_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_body);

    if ((p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ)) == NULL)
        goto error;

    if (frreport_data_add_body(p_st_report_data, p_st_body) != FR_SUCC)
        goto error;
    // 重新设置响应的源地址、源端口、目的地址、目的端口
    if (FrReportOpt_set_srcIp2(p_st_report_data, p_cnaps2_stmt->ui_src_ip) == FR_FAIL ||
        FrReportOpt_set_srcPort(p_st_report_data, p_cnaps2_stmt->us_src_port) == FR_FAIL ||
        FrReportOpt_set_dstIp2(p_st_report_data, p_cnaps2_stmt->ui_dst_ip) == FR_FAIL ||
        FrReportOpt_set_dstPort(p_st_report_data, p_cnaps2_stmt->us_dst_port) == FR_FAIL)
        goto error;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) != FR_SUCC)
        goto error;

    return FR_SUCC;
error:
    frreport_body_free(&p_st_body);
    frreport_data_free(&p_st_report_data);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  上报响应
*  ARGS     :  p_st_conn                                (ct)
*           :  p_st_hash_report                         (保存Frreport_data)
*           :  p_cnaps2_stmt                         (从上下文中取出来的Session)
*           :  l_resp_start_timestamp                   (响应的开始时间)
*           :  l_resp_end_timestamp                     (响应的结束时间)
*           :  l_send_time                              (响应的发送时间)
*           :  l_data_bytes                             (响应的字节数)
*           :  p_req_mesg_type                              (hvps.111.001.01)
*           :  p_req_mesg_type_cn                           (客户发起汇兑业务)
*           :  p_mesg_id                                (通信级标识号)
*           :  p_mesg_ref_id                            (通信级参考号)
*           :  i_resp_code                              (0或者-1)
*           :  p_resp_codestring                        (PM1I0000)
*           :  p_resp_error_mesg                        (PM1I0000:支付报文传输平台-NPC开放系统-处理成功)
*  RTN      :  0                                        (FR_SUCC)
*              1                                        (FR_FAIL)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __cnaps2_report_resp(Conntrack *p_st_conn
                                    , Frhash_header *p_st_hash_report
                                    , L7_cnaps2_stmt *p_cnaps2_stmt
                                    , long long ll_resp_start_timestamp
                                    , long long ll_resp_end_timestamp
                                    , long long ll_send_time
                                    , long long ll_data_bytes
                                    , char *p_mesg_type
                                    , char *p_mesg_type_cn
                                    , char *p_mesg_id
                                    , char *p_mesg_ref_id
                                    , int i_resp_code
                                    , char *p_resp_codestring
                                    , char *p_resp_error_mesg
                                    , char *p_mq_message)
{
    CNAPS2_PRINT_WARN("__cnaps2_report_resp...\n");
    Frreport_body_data *p_st_body = NULL;
    Frreport_data *p_st_report_data = NULL;

    if ((p_st_body = frreport_body_new_l7(p_st_conn)) == NULL)
        goto error;
    if (FRREPORT_BODY_L7LIST_SET_COMM(p_st_body, &(p_cnaps2_stmt->p_report_comm)) != FR_SUCC)
        goto error;
    if (FRREPORT_BODY_L7LIST_SET_REQ(p_st_body, &(p_cnaps2_stmt->p_report_req)) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_RESP_START_TIMESTAMP, (long) ll_resp_start_timestamp) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_RESP_END_TIMESTAMP, (long) ll_resp_end_timestamp) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_RESP_SERVER_TIME_US, (long) (ll_resp_start_timestamp - p_cnaps2_stmt->ll_req_end_timestamp) * 1000) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, (long) ll_send_time) != FR_SUCC)
        goto error;
    if (frreport_body_l7_add_long(p_st_body, APM_REPORT_KEY_RESP_DATA_BYTES, (long) ll_data_bytes) != FR_SUCC)
        goto error;

    if (frreport_body_l7_add_int(p_st_body, APM_REPORT_KEY_RESP_CODE, i_resp_code) == FR_FAIL)
        goto error;
    if (p_resp_codestring && frreport_body_l7_add_str(p_st_body, APM_REPORT_KEY_RESP_CODE_STRING, p_resp_codestring) == FR_FAIL)
        goto error;
    if (p_resp_error_mesg && frreport_body_l7_add_str(p_st_body, APM_REPORT_KEY_RESP_ERR_MSG, p_resp_error_mesg) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "response.mq.cnaps2.mesg_id", p_mesg_id) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "response.mq.cnaps2.mesg_ref_id", p_mesg_ref_id) == FR_FAIL)
        goto error;
    if (frreport_body_l7_add_str(p_st_body, "response.cnaps2.mesg", p_mq_message) == FR_FAIL)
        goto error;

    if ((p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP)) == NULL)
        goto error;

    if (frreport_data_add_body(p_st_report_data, p_st_body) != FR_SUCC)
        goto error;
    // 重新设置响应的源地址、源端口、目的地址、目的端口
    if (FrReportOpt_set_srcIp2(p_st_report_data, p_cnaps2_stmt->ui_src_ip) == FR_FAIL ||
        FrReportOpt_set_srcPort(p_st_report_data, p_cnaps2_stmt->us_src_port) == FR_FAIL ||
        FrReportOpt_set_dstIp2(p_st_report_data, p_cnaps2_stmt->ui_dst_ip) == FR_FAIL ||
        FrReportOpt_set_dstPort(p_st_report_data, p_cnaps2_stmt->us_dst_port) == FR_FAIL)
        goto error;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) != FR_SUCC)
        goto error;

    CNAPS2_PRINT_CRIT("resp message_type:[%s]\n", p_mesg_type);
    CNAPS2_PRINT_CRIT("resp message_type_cn:[%s]\n", p_mesg_type_cn);

    return FR_SUCC;
error:
    frreport_body_free(&p_st_body);
    frreport_data_free(&p_st_report_data);
    return FR_FAIL;
}

int cnaps2_parse(Conntrack *p_st_conn
                , Frreport_data *p_st_report_data
                , Frhash_header *p_st_hash_report
                , int i_is_mq_req)
{
#if APM_CNAPS2_DISABLED
    return FR_FAIL;
#endif
    CNAPS2_PRINT_INFO("cnaps2_parse...\n");
    int i_cnaps2_version = CNAPS2_IS_FAIL;
    Frvar_field *p_st_field = NULL;
    char arr_mesg_type[CNAPS2_HEADER_MESG_TYPE_LEN + 1] = {0};
    char arr_mesg_id[CNAPS2_HEADER_MESG_ID_LEN + 1] = {0};
    char arr_mesg_ref_id[CNAPS2_HEADER_MESG_REF_ID_LEN + 1] = {0};
    unsigned int ui_mesg_body_offset = 0;
    char arr_mesg_type_cn[CNAPS2_HEADER_MESG_TYPE_CN_LEN] = {0};
    int i_is_resp = FR_NO;
    L7_cnaps2_stmt *p_cnaps2_stmt = NULL;
    L7_cnaps2_stmt *p_cnaps2_stmt_resp = NULL;
    char arr_stmt_key[21] = {0};
    char *p_resp_code = NULL;
    char *p_resp_codestring = NULL;
    long long ll_start_timestamp = 0L;
    long long ll_end_timestamp = 0L;
    long long ll_duration_time = 0L;
    long long ll_data_bytes = 0L;
    int i_resp_code_short = 0;
    // PM1I0000:支付报文传输平台-NPC开放系统-处理成功
    char arr_resp_codestring_converted[sizeof(arr_cnaps2_syscode_maps[0].arr_name) + sizeof(arr_cnaps2_nodecode_maps[0].arr_name) + sizeof(arr_cnaps2_prccode_maps[0].arr_name) + 13] = {0};
    char *p_mq_message = NULL;
    char *p_title = NULL;

    if ( ((i_is_mq_req == FR_YES && (p_st_field = FrReportOpt_get_field(p_st_report_data, "request.mq.message.text", 0))) ||
          (i_is_mq_req == FR_NO && (p_st_field = FrReportOpt_get_field(p_st_report_data, "response.mq.message.text.1", 0))) ||
            (p_st_field = FrReportOpt_get_field(p_st_report_data, "notify.mq.message.text.1", 0))) &&
        p_st_field->em_data_type == FRSTRING &&
        (i_cnaps2_version = __cnaps2_detect(p_st_field->field_value.p_value, strlen(p_st_field->field_value.p_value))) != CNAPS2_IS_FAIL &&
        __cnaps2_parse_header(p_st_field->field_value.p_value, arr_mesg_type, arr_mesg_id, arr_mesg_ref_id, i_cnaps2_version) == FR_SUCC &&
        __cnaps2_skip_digital_signature(p_st_field->field_value.p_value, &ui_mesg_body_offset, i_cnaps2_version) == FR_SUCC)
    {
        if (cnaps2_parse_xml(p_st_field->field_value.p_value + ui_mesg_body_offset,
                             (int) strlen(p_st_field->field_value.p_value + ui_mesg_body_offset),
                             &p_resp_code, &p_resp_codestring) == FR_SUCC)
        {
            p_mq_message = p_st_field->field_value.p_value;
            // 将 hvps.111.001.01 转换成 客户发起汇兑业务
            __cnaps2_mesg_type_to_cn(arr_mesg_type, arr_mesg_type_cn);
            // 根据 message type(hvps.111.001.01)判断是否是响应
            i_is_resp = __cnaps2_mesg_is_resp(arr_mesg_type);

#if APM_CNAPS2_DBG
            char arr_ip_src[56], arr_ip_dst[56];
            unsigned int ui_src_ip;
            unsigned short us_src_port;
            unsigned int ui_dst_ip;
            unsigned short us_dst_port;
            if (i_is_mq_req == FR_YES)
            {
                ui_src_ip = FrReportOpt_get_srcIp(p_st_report_data);
                us_src_port = FrReportOpt_get_srcPort(p_st_report_data);
                ui_dst_ip = FrReportOpt_get_dstIp(p_st_report_data);
                us_dst_port = FrReportOpt_get_dstPort(p_st_report_data);
            }
            else
            {
                ui_src_ip = FrReportOpt_get_dstIp(p_st_report_data);
                us_src_port = FrReportOpt_get_dstPort(p_st_report_data);
                ui_dst_ip = FrReportOpt_get_srcIp(p_st_report_data);
                us_dst_port = FrReportOpt_get_srcPort(p_st_report_data);
            }
            snprintf(arr_ip_src, sizeof(arr_ip_src), "%s", int_ntoa(ui_src_ip));
            snprintf(arr_ip_dst, sizeof(arr_ip_src), "%s", int_ntoa(ui_dst_ip));
            CNAPS2_PRINT_DBG("["KLIMEGREEN"%s:%d"RESET"] to ["KLIMEGREEN"%s:%d"RESET"]\n", arr_ip_src, us_src_port, arr_ip_dst, us_dst_port);
#endif
            CNAPS2_PRINT_CRIT("message_type:[%s]\n", arr_mesg_type);
            CNAPS2_PRINT_CRIT("message_type_cn:[%s]\n", arr_mesg_type_cn);
            CNAPS2_PRINT_CRIT("mesg_id:[%s]\n", arr_mesg_id);
            CNAPS2_PRINT_CRIT("mesg_ref_id:[%s]\n", arr_mesg_ref_id);
            CNAPS2_PRINT_CRIT("i_is_resp:[%s]\n", FR_YESNO2STR(i_is_resp));

            if (i_is_resp == FR_NO) // 请求
            {
                if ((p_cnaps2_stmt = (L7_cnaps2_stmt *) frmalloc(sizeof(L7_cnaps2_stmt))) == NULL)
                {
                    CNAPS2_MALLOCK_ERR;
                    goto error;
                }
                memset(p_cnaps2_stmt, 0x00, sizeof(L7_cnaps2_stmt));

                if (i_is_mq_req == FR_YES)
                {
                    p_cnaps2_stmt->ui_src_ip = FrReportOpt_get_srcIp(p_st_report_data);
                    p_cnaps2_stmt->us_src_port = 50011;
                    p_cnaps2_stmt->ui_dst_ip = FrReportOpt_get_dstIp(p_st_report_data);
                    p_cnaps2_stmt->us_dst_port = 50011;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_START_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_start_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_start_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_END_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_end_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_end_timestamp = p_st_field->field_value.ll_value;
                    p_cnaps2_stmt->ll_req_end_timestamp = ll_end_timestamp;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_DATA_BYTES, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_data_bytes = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_data_bytes = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_SEND_TIME_US, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_duration_time = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_duration_time = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_TRANS_TITLE, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        p_title = p_st_field->field_value.p_value;

                    if (__cnaps2_report_req(p_st_conn, p_st_hash_report, p_cnaps2_stmt, ll_start_timestamp, ll_end_timestamp,
                                            ll_duration_time, ll_data_bytes, p_title, arr_mesg_type, arr_mesg_type_cn,
                                            arr_mesg_id, arr_mesg_ref_id, p_mq_message) != FR_SUCC)
                        goto error;
                }
                else
                {
                    p_cnaps2_stmt->ui_src_ip = FrReportOpt_get_dstIp(p_st_report_data);
                    p_cnaps2_stmt->us_src_port = 50011;
                    p_cnaps2_stmt->ui_dst_ip = FrReportOpt_get_srcIp(p_st_report_data);
                    p_cnaps2_stmt->us_dst_port = 50011;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_START_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_start_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_start_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_END_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_end_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_end_timestamp = p_st_field->field_value.ll_value;
                    p_cnaps2_stmt->ll_req_end_timestamp = ll_end_timestamp;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_DATA_BYTES, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_data_bytes = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_data_bytes = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_duration_time = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_duration_time = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_TRANS_TITLE, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        p_title = p_st_field->field_value.p_value;

                    if (__cnaps2_report_req(p_st_conn, p_st_hash_report, p_cnaps2_stmt, ll_start_timestamp, ll_end_timestamp,
                                        ll_duration_time, ll_data_bytes, p_title, arr_mesg_type, arr_mesg_type_cn,
                                            arr_mesg_id, arr_mesg_ref_id, p_mq_message) != FR_SUCC)
                        goto error;
                }

                p_cnaps2_stmt->p_req_mesg_type = frstrdup(arr_mesg_type);
                p_cnaps2_stmt->p_req_mesg_type_cn = frstrdup(arr_mesg_type_cn);
                p_cnaps2_stmt->p_req_mesg_id = frstrdup(arr_mesg_id);
                p_cnaps2_stmt->p_req_mesg_ref_id = frstrdup(arr_mesg_ref_id);

                snprintf(arr_stmt_key, sizeof(arr_stmt_key), "%s", arr_mesg_id);
                CNAPS2_PRINT_NOTICE("try to get stmt resp:[%s]\n", arr_stmt_key);
                if ((p_cnaps2_stmt_resp = __cnaps2_get_report_stmt(arr_stmt_key, (unsigned int) strlen(arr_stmt_key))) != NULL)
                {
                    CNAPS2_PRINT_NOTICE("get stmt resp:[%s] success\n", arr_stmt_key);

                    if (__cnaps2_report_resp(p_st_conn, p_st_hash_report, p_cnaps2_stmt, p_cnaps2_stmt_resp->ll_resp_start_timestamp
                            , p_cnaps2_stmt_resp->ll_resp_end_timestamp, p_cnaps2_stmt_resp->ll_resp_download_time
                            , p_cnaps2_stmt_resp->ll_resp_data_bytes, p_cnaps2_stmt->p_req_mesg_type, p_cnaps2_stmt->p_req_mesg_type_cn
                            , p_cnaps2_stmt_resp->p_resp_mesg_id, p_cnaps2_stmt_resp->p_resp_mesg_ref_id
                            , p_cnaps2_stmt_resp->i_resp_code_short, p_cnaps2_stmt_resp->p_resp_code
                            , p_cnaps2_stmt_resp->p_resp_codestring, p_cnaps2_stmt_resp->p_resp_mq_message) != FR_SUCC)
                        goto error;
                    cnaps2_stmt_free(&p_cnaps2_stmt);
                    cnaps2_stmt_free(&p_cnaps2_stmt_resp);
                }
                else
                {
                    CNAPS2_PRINT_INFO("get stmt resp:[%s] failed\n", arr_stmt_key);
                    CNAPS2_PRINT_NOTICE("try to put stmt req:[%s]\n", arr_stmt_key);
                    if (__cnaps2_put_report_stmt(arr_stmt_key, (unsigned int) strlen(arr_stmt_key), &p_cnaps2_stmt) != FR_SUCC)
                    {
                        CNAPS2_PRINT_EMERG("put stmt req:[%s] failed\n", arr_stmt_key);
                        goto error;
                    }
                    CNAPS2_PRINT_NOTICE("put stmt req:[%s] success\n", arr_stmt_key);
                }
            }
            else // 响应
            {
                if (p_resp_code)
                    CNAPS2_PRINT_ALERT("\tresp_code:[%s]\n", p_resp_code);

                i_resp_code_short = __cnaps2_resp_code_short(p_resp_code);
                CNAPS2_PRINT_ALERT("\tresp_code_short:[%d]\n", i_resp_code_short);

                if (p_resp_codestring)
                    CNAPS2_PRINT_ALERT("\tresp_codestring:[%s]\n", p_resp_codestring);
                else
                {
                    if (__cnaps2_convert_resp_code(p_resp_code, arr_resp_codestring_converted, sizeof(arr_resp_codestring_converted)) == FR_SUCC)
                    {
                        CNAPS2_PRINT_ALERT("\tresp_codestring_converted:[%s]\n", arr_resp_codestring_converted);
                        p_resp_codestring = frstrdup(arr_resp_codestring_converted);
                    }
                }

                if (i_is_mq_req == FR_YES)
                {
                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_START_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_start_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_start_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_END_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_end_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_end_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_DATA_BYTES, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_data_bytes = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_data_bytes = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_REQ_SEND_TIME_US, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_duration_time = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_duration_time = p_st_field->field_value.ll_value;
                }
                else
                {
                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_START_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_start_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_start_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_END_TIMESTAMP, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_end_timestamp = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_end_timestamp = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_DATA_BYTES, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_data_bytes = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_data_bytes = p_st_field->field_value.ll_value;

                    if ((p_st_field = FrReportOpt_get_field(p_st_report_data, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, 0)) == NULL)
                        goto error;
                    if (p_st_field->em_data_type == FRSTRING)
                        ll_duration_time = atoll(p_st_field->field_value.p_value);
                    else if (p_st_field->em_data_type == FRLONG)
                        ll_duration_time = p_st_field->field_value.ll_value;
                }

                if (strcmp(arr_mesg_ref_id, "00000000000000000000") == 0)
                    snprintf(arr_stmt_key, sizeof(arr_stmt_key), "%s", arr_mesg_id);
                else
                    snprintf(arr_stmt_key, sizeof(arr_stmt_key), "%s", arr_mesg_ref_id);
                CNAPS2_PRINT_NOTICE("try to get stmt req:[%s]\n", arr_stmt_key);
                if ((p_cnaps2_stmt = __cnaps2_get_report_stmt(arr_stmt_key, (unsigned int) strlen(arr_stmt_key))) != NULL)
                {
                    CNAPS2_PRINT_NOTICE("get stmt req:[%s] success\n", arr_stmt_key);

                    if (__cnaps2_report_resp(p_st_conn, p_st_hash_report, p_cnaps2_stmt, ll_start_timestamp, ll_end_timestamp
                            , ll_duration_time, ll_data_bytes, p_cnaps2_stmt->p_req_mesg_type, p_cnaps2_stmt->p_req_mesg_type_cn
                            , arr_mesg_id, arr_mesg_ref_id, i_resp_code_short
                            , p_resp_code, p_resp_codestring, p_mq_message) != FR_SUCC)
                        goto error;
                    cnaps2_stmt_free(&p_cnaps2_stmt);
                }
                else
                {
                    // 如果没找到对应的请求,则把当前这个响应存到hash中去
                    CNAPS2_PRINT_EMERG("get stmt req:[%s] failed\n", arr_stmt_key);

                    if ((p_cnaps2_stmt = (L7_cnaps2_stmt *) frmalloc(sizeof(L7_cnaps2_stmt))) == NULL)
                    {
                        CNAPS2_MALLOCK_ERR;
                        goto error;
                    }
                    memset(p_cnaps2_stmt, 0x00, sizeof(L7_cnaps2_stmt));

                    p_cnaps2_stmt->ll_resp_start_timestamp = ll_start_timestamp;
                    p_cnaps2_stmt->ll_resp_end_timestamp = ll_end_timestamp;
                    p_cnaps2_stmt->ll_resp_download_time = ll_duration_time;
                    p_cnaps2_stmt->ll_resp_data_bytes = ll_data_bytes;
                    p_cnaps2_stmt->p_resp_mesg_id = frstrdup(arr_mesg_id);
                    p_cnaps2_stmt->p_resp_mesg_ref_id = frstrdup(arr_mesg_ref_id);
                    p_cnaps2_stmt->i_resp_code_short = i_resp_code_short;
                    p_cnaps2_stmt->p_resp_code = frstrdup(p_resp_code);
                    p_cnaps2_stmt->p_resp_codestring = frstrdup(p_resp_codestring);
                    p_cnaps2_stmt->p_resp_mq_message = frstrdup(p_mq_message);
                    p_cnaps2_stmt->p_resp_mesg_type = frstrdup(arr_mesg_type);
                    p_cnaps2_stmt->p_resp_mesg_type_cn = frstrdup(arr_mesg_type_cn);

                    CNAPS2_PRINT_NOTICE("try to put stmt resp:[%s]\n", arr_stmt_key);
                    if (__cnaps2_put_report_stmt(arr_stmt_key, (unsigned int) strlen(arr_stmt_key), &p_cnaps2_stmt) != FR_SUCC)
                    {
                        CNAPS2_PRINT_EMERG("put stmt resp:[%s] failed\n", arr_stmt_key);
                        goto error;
                    }
                    CNAPS2_PRINT_NOTICE("put stmt resp:[%s] success\n", arr_stmt_key);
                }

            }

            CNAPS2_PRINT_DBG("cnaps2_parse success...\n\n");
        }
    }
    else
        goto error;

    __clear_timeout_stmt();

    cnaps2_free((void **) &p_resp_code);
    cnaps2_free((void **) &p_resp_codestring);
    return FR_SUCC;
error:
    CNAPS2_PRINT_EMERG("cnaps2_parse error...\n\n");
    cnaps2_stmt_free(&p_cnaps2_stmt);
    cnaps2_stmt_free(&p_cnaps2_stmt_resp);
    cnaps2_free((void **) &p_cnaps2_stmt);
    cnaps2_free((void **) &p_resp_code);
    cnaps2_free((void **) &p_resp_codestring);
    return FR_FAIL;
}
